package gla.centralhotel.dao;

import gla.centralhotel.dao.interfaces.IManagerDAO;
import gla.centralhotel.exception.CollectionRetrieverException;
import gla.centralhotel.exception.IllegalAuthenticationException;
import gla.centralhotel.exception.ManagerSubscriptionException;
import gla.centralhotel.exception.NoUserFoundException;
import gla.centralhotel.model.Country;
import gla.centralhotel.model.Manager;
import gla.centralhotel.model.Zipcode;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author Rivo
 */
@Stateless
public class ManagerDAO implements IManagerDAO {

    @PersistenceContext
    private EntityManager em;

    private Manager create(Manager manager) {
        em.persist(manager);
        return manager;
    }

    private Manager edit(Manager manager) {
        em.merge(manager);
        return manager;
    }

    public void remove(Manager manager) {
        em.remove(em.merge(manager));
    }

    public Manager find(Object id) {
        return em.find(gla.centralhotel.model.Manager.class, id);
    }

    public List<Manager> findAll() {
        return em.createQuery("select object(o) from Manager as o").getResultList();
    }
    
    /**
     * Trouver le manager par son e-mail
     * @param email
     * @return
     * @throws javax.persistence.NoResultException
     * @throws javax.persistence.NonUniqueResultException
     */
    public Manager findManagerByEmail(String email) throws NoUserFoundException{
        Query q = em.createNamedQuery("Manager.findByEmail");
        q.setParameter("email", email);
        try{
            return (Manager) q.getSingleResult();
        }catch(NoResultException noREx){
            throw new NoUserFoundException("Aucun utilisateur n'a cet e-mail"+email);
        }catch(NonUniqueResultException e){
            throw new NoUserFoundException("ECHEC !!!");
        }
    }
    
    /**
     * Identifie l'utilisateur par "login - password"
     * @param email
     * @param pwd
     * @return
     * @throws javax.persistence.NoResultException
     * @throws javax.persistence.NonUniqueResultException
     */
    public Manager findManagerByEmailPassword(String email, String pwd) throws IllegalAuthenticationException{
        String query = "select mgr from Manager as mgr where mgr.email = :email and mgr.password = :pwd";
        Query q = em.createQuery(query);
        q.setParameter("email", email);
        q.setParameter("pwd", pwd);
        try{
            return (Manager) q.getSingleResult();
        }catch(NoResultException noREx){
            throw new IllegalAuthenticationException("Aucun utilisateur trouvé!");
        }catch(NonUniqueResultException noUResEx){
            throw new IllegalAuthenticationException("ERREUR GRAVE, plusieurs utilisateurs pour un e-mail !!");
        }
    }
    
    /**
     * MAJ Infos manager d'hotel
     * @param manager
     * @return
     */
    public Manager updateManager(Manager manager)throws ManagerSubscriptionException, IllegalAuthenticationException{
        if(manager.getId() != null && manager.getEmail() != null && manager.getPassword() != null){
            try {
                Manager tmp = findManagerByEmail(manager.getEmail());
                if (tmp.getId().compareTo(manager.getId()) == 0) {
                    return edit(manager);
                } else {
                    throw new IllegalAuthenticationException("Erreur de mise à jour :" + " id en base est différent de celui à mettre à jour");
                }
            } catch (NoUserFoundException ex) {
                Logger.getLogger(ManagerDAO.class.getName()).log(Level.SEVERE, null, ex);
                throw new IllegalAuthenticationException("Aucun user trouvé !!");
            }
        }else{
            throw new ManagerSubscriptionException("Mise à jour impossible les " +
                    "infos suivantes sont incorrectes : id et/ou email et/ou mote de passe");
        }
    }

    /**
     * Permet de recuperer une collection de manager d'hotel en passant en parametre
     * un zipcode
     * @param zipcode
     * @return
     * @throws gla.centralhotel.exception.CollectionRetrieverException
     */
    public ArrayList<Manager> getAllManagerByZipcode(Zipcode zipcode) throws CollectionRetrieverException {
        String query = "select mgr from Manager as mgr where mgr.refZipcode = : refZipcode";
        Query q = em.createQuery(query);
        q.setParameter("refZipcode", zipcode);

        try {
            return new ArrayList(q.getResultList());
        } catch (IllegalStateException ex) {
            ex.printStackTrace();
            throw new CollectionRetrieverException("Erreur de récupération des manger en fonction du zipcode");
        }
    }
    
    /**
     * Permet de recuperer une collection de manager d'hotel en passant en parametre
     * un country
     * @param country
     * @return
     * @throws gla.centralhotel.exception.CollectionRetrieverException
     */
    public ArrayList<Manager> getAllManagerByCountry(Country country) throws CollectionRetrieverException{
        String query = "select mgr from Manager as mgr where mgr.refCountry = : refCountry";
        Query q = em.createQuery(query);
        q.setParameter("refCountry", country);

        try {
            return new ArrayList(q.getResultList());
        } catch (IllegalStateException ex) {
            ex.printStackTrace();
            throw new CollectionRetrieverException("Erreur de récupération des manager en fonction du zipcode");
        }
    }

    /**
     * Ajoute un manager d'hotel et vérifie l'unicité du mail (mot de passe implicite)
     * @param manager
     * @return
     */
    public Manager saveManager(Manager manager) throws ManagerSubscriptionException, IllegalAuthenticationException {
        String email = "select mgr from Manager as mgr where mgr.email = :email";
        if (manager.getId() == null && manager.getEmail() != null && manager.getPassword() != null) {
            Query mgrMail = em.createQuery(email);
            mgrMail.setParameter("email", manager.getEmail());
            List<Manager> mgrList = mgrMail.getResultList();
            if (mgrList.size() == 0) {
                manager = create(manager);
                return manager;
            } else {
                throw new ManagerSubscriptionException("Email et mot de passe déjà utilisés");
            }
        } else {
            throw new IllegalAuthenticationException("E-mail ou mot de passe : null !!!!");
        }
    }
}
